#include "Connector.h"
#include "Helper.h"
#include "Initializers/NguyenWidrowFunction.h"

using namespace NeuralPlusPlus::Core;
using namespace NeuralPlusPlus::Core::Initializers;

NeuralPlusPlus::Core::Connector::Connector( Layer *sourceLayer, Layer *targetLayer, ConnectionModeType connectionMode )
	{
	// Validate
	Helper::ValidateNotNull(sourceLayer, "sourceLayer");
	Helper::ValidateNotNull(targetLayer, "targetLayer");

	targetLayer->SourceConnectors.push_back(this);
	sourceLayer->TargetConnectors.push_back(this);

	this->SourceLayer = sourceLayer;
	this->TargetLayer = targetLayer;
	this->ConnectionMode = connectionMode;
	this->Initializer = new NguyenWidrowFunction();

	switch (connectionMode)
		{
		case ConnectionModeType::Complete:
			SynapsesLength = sourceLayer->NeuronsLength * targetLayer->NeuronsLength;
			Synapses = new ISynapse*[SynapsesLength];
			break;
		case ConnectionModeType::OneOne:
			if (sourceLayer->NeuronsLength == targetLayer->NeuronsLength)
				{
				SynapsesLength = sourceLayer->NeuronsLength;
				Synapses = new ISynapse*[SynapsesLength];
				break;
				}
		}

	}

void NeuralPlusPlus::Core::Connector::Jitter( double jitterNoiseLimit )
	{
	for (int i = 0; i < SynapsesLength; i++)
		{
		Synapses[i]->Jitter(jitterNoiseLimit);
		}
	}

std::vector<ISynapse*>* NeuralPlusPlus::Core::Connector::GetSourceSynapses( INeuron *neuron )
	{
	std::vector<ISynapse*> *sourceSynapses = new std::vector<ISynapse*>();

	int sourceSynapsesCount = neuron->SourceSynapses.size();
	for(int i=0;i<sourceSynapsesCount;i++)
		{
		if(neuron->SourceSynapses[i]->Parent == this)
			{
			sourceSynapses->push_back(neuron->SourceSynapses[i]);
			}
		}
	return sourceSynapses;
	}

std::vector<ISynapse*>* NeuralPlusPlus::Core::Connector::GetTargetSynapses( INeuron *neuron )
	{
	std::vector<ISynapse*> *targetSynapses = new std::vector<ISynapse*>();

	int targetSynapsesCount = neuron->TargetSynapses.size();
	for(int i=0;i<targetSynapsesCount;i++)
		{
		if(neuron->TargetSynapses[i]->Parent == this)
			{
			targetSynapses->push_back(neuron->TargetSynapses[i]);
			}
		}
	return targetSynapses;
	}

NeuralPlusPlus::Core::Connector::~Connector()
	{
	for (int i = 0; i < SynapsesLength; i++)
		{
		delete Synapses[i];
		Synapses[i] =NULL;
		}
	delete[] Synapses;
	SynapsesLength =0;
	delete Initializer;
	Initializer = NULL;
	}